#pragma once

#include <Windows.h>
#include <list>

namespace CommLib
{

#define STATE_ERROR_EVENT		-1
#define STATE_ERROR_CONNECT		-2
#define STATE_ERROR_READ		-3
#define STATE_CONNECTED			1
#define STATE_DISCONNECTED		2

	class Pipe
	{
		struct _BUFFER
		{
			_BUFFER()
			{
				size = 0;
				ptr = 0;
			}
			unsigned int size;
			unsigned char *ptr;
		};

		typedef std::list<_BUFFER> BUFLIST;

	public:
		Pipe( bool bAutoUpdate, bool bHasSendBuffer = false );
		~Pipe();

		class IEventHandler
		{
		public:
			virtual bool	OnMsgArrived( void * pData, unsigned int uSize ) = 0;
			virtual bool	OnStateChanged( int StateNo ) = 0;
		};

		bool Create( const char *pszName );
		bool Open( const char *pszName ); 
		void Destroy();

		void SetEventHandler( Pipe::IEventHandler *pHandler );

		int SendMsg( const void *pData, unsigned int uSize );
		void Update();

	protected:
		Pipe::IEventHandler * m_pEventHandler;

		HANDLE m_hThread;
		HANDLE m_hPipe;
		HANDLE m_hRecvEvent;
		HANDLE m_hSendEvent;
		HANDLE m_hDestroyEvent;

		bool m_bAutoUpdate;
		bool m_bHasSendBuffer;

		BUFLIST m_lstBuffers;
		BUFLIST m_lstSendBuffers;

		CRITICAL_SECTION m_csBuffer;
		CRITICAL_SECTION m_csSend;
		CRITICAL_SECTION m_csSendBuffer;

		bool m_bConnected;
		bool m_bSlave;

		std::string m_strPipeName;

		bool HandleStateChange( int StateNo );
		bool HandleRecvData( void * pData, unsigned int uSize );
		bool DoState( int StateNo );

		int _ReadData( void *pData, unsigned int uSize );
		int _WriteData( const void *pData, unsigned int uSize );
		int _WaitConnect();

		unsigned int Thread();
		friend unsigned int _stdcall Thread( void *lParam );
	};

}